﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using Vbyte.SharpOrm.Adapter;
using Vbyte.SharpOrm.SqlDb;

namespace Vbyte.SharpOrm.SqLite
{
    /// <summary>
    /// 针对SqLite的适配
    /// </summary>
    public class SqLiteAdapter : ISqlDbAdapter
    {
        /// <summary>
        /// Sql数据类型映射词典
        /// </summary>
        private static Dictionary<string, string> SqlDbTypeMapDict = new Dictionary<string, string>();

        /// <summary>
        /// Initializes a new instance of the <see cref="SqLiteAdapter"/> class.
        /// </summary>
        public SqLiteAdapter()
            : base()
        {
            InitializeDict();
        }

        private void InitializeDict()
        {
            if (SqlDbTypeMapDict.Count == 0)
            {
                SqlDbTypeMapDict.Add(typeof(Single).FullName, "FLOAT");
                SqlDbTypeMapDict.Add(typeof(double).FullName, "REAL");
                SqlDbTypeMapDict.Add(typeof(decimal).FullName, "NUMERIC");
                SqlDbTypeMapDict.Add(typeof(long).FullName, "INTEGER");
                SqlDbTypeMapDict.Add(typeof(int).FullName, "INTEGER");
                SqlDbTypeMapDict.Add(typeof(short).FullName, "INTEGER");
                SqlDbTypeMapDict.Add(typeof(byte).FullName, "INTEGER");
                SqlDbTypeMapDict.Add(typeof(Guid).FullName, "uniqueidentifier");
                SqlDbTypeMapDict.Add(typeof(bool).FullName, "BIT");
                SqlDbTypeMapDict.Add(typeof(DateTime).FullName, "DATETIME");
                SqlDbTypeMapDict.Add(typeof(byte[]).FullName, "IMAGE");
            }
        }

        #region ISqlDbAdapter 成员

        /// <summary>
        /// 获取针对NET CLR基本数据类型的Sql数据类型转换
        /// </summary>
        /// <param name="clrType">NET CLR基本基本类型</param>
        /// <param name="maxLength">可为空的最大长度限制</param>
        /// <returns></returns>
        public string GetNativeType(Type clrType, int? maxLength)
        {
            string strSqlType = "text(255)";
            if (clrType == typeof(string))
            {
                if (maxLength.HasValue)
                {
                    if (maxLength.Value == int.MaxValue || maxLength.Value > 4000)
                    {
                        strSqlType = "text";
                    }
                    else
                    {
                        strSqlType = "text(" + maxLength.Value.ToString() + ")";
                    }
                }
            }
            else if (clrType.IsGenericType
                && clrType.GetGenericTypeDefinition() == typeof(Nullable<>).GetGenericTypeDefinition())
            {
                string keyType = Nullable.GetUnderlyingType(clrType).FullName;
                if (SqlDbTypeMapDict.ContainsKey(keyType))
                {
                    strSqlType = SqlDbTypeMapDict[keyType];
                }
            }
            else
            {
                if (SqlDbTypeMapDict.ContainsKey(clrType.FullName))
                {
                    strSqlType = SqlDbTypeMapDict[clrType.FullName];
                }
            }
            return strSqlType;
        }

        /// <summary>
        /// 获取指定表内最新产生标志的SQL语句获取文本
        /// </summary>
        /// <param name="currentTabName">当前表名，如果为null或空则返回全局标志。</param>
        /// <returns>标志的SQL语句获取文本</returns>
        public string GetIdentitySql(string currentTabName)
        {
            return "SELECT last_insert_rowid();";
        }

        /// <summary>
        /// 标志该数据适配器是否有自己的数据分页实现
        /// </summary>
        /// <returns>实现则为true，否则为false。</returns>
        public bool HasImplementCustomPage()
        {
            return true;
        }

        /// <summary>
        /// 获取满足实例条件的分页数据
        /// </summary>
        /// <param name="dbInstance">数据库辅助实例</param>
        /// <param name="builderInstance">在实例样本上产生的SQL构建适配器</param>
        /// <param name="tabDef">获取实例表定义（备用:获取主键、max函数运算信息）</param>
        /// <param name="currentPage">当前数据页页次</param>
        /// <param name="pageSize">每页显示记录条数</param>
        /// <param name="sharedOpenConnection">当前存在的已打开连接的数据库连接</param>
        /// <param name="command">已生成的数据库操作命令实例</param>
        /// <returns>满足条件的内容数据表</returns>
        public DataTable GetPagedDataTable(ISqlDb dbInstance, ISqlBuilderAdapter builderInstance,
            SqlTable tabDef, int currentPage, int pageSize, DbConnection sharedOpenConnection, DbCommand command)
        {
            Database Svr = (Database)dbInstance;
            /*
                如果我要去11-20的Account表的数据
                Select * From Account Limit 9 Offset 10;
                以上语句表示从Account表获取数据，跳过10行，取9行
                也可以这样写 select * from account limit 10,9 和上面的的效果一样。
                这种写法MySQL也支持。 
             */
            command.CommandText = string.Format("Select {1} from {2} {3} {4} {5} limit {6},{0} ",
                    pageSize,
                    string.Join(",", builderInstance.FieldNamesList), //字段列表
                    builderInstance.VirtualTable,                     //数据来源表
                    builderInstance.SqlCondition,                     //条件限制
                    builderInstance.SqlGroupBy,                       //分组
                    builderInstance.SqlOrderBy,
                    (currentPage - 1) * pageSize);

            return Svr.GetDataTable(sharedOpenConnection, command);
        }

        #endregion
    }
}
